package org.maxkey.portal.api.interceptor;

import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.maxkey.portal.api.controller.LoginController;
import org.maxkey.portal.api.handler.WebAuthenticationHandler;
import org.maxkey.portal.core.authentication.CurrentAccount;
import org.maxkey.portal.core.cam.Constants;
import org.maxkey.portal.core.cam.CurrentThreadLocal;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@Slf4j
@Configuration
public class InterceptorSupport implements HandlerInterceptor {

    @Autowired
    @Qualifier("webAuthenticationHandler")
    private WebAuthenticationHandler webAuthenticationHandler;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        HandlerMethod method=(HandlerMethod)handler;
        log.info("execute class {} : method name {}",method.getBean().getClass(),method.getMethod().getName());
        if(method.getBean().getClass().equals(LoginController.class) && method.getMethod().getName().equals("login"))return true;
        if(!interceptorTokenHeaderAndParam(request,response)){
            writeContent403(response);
            return false;
        }
        return true;
    }

    /**
     * 获取access_token参数，优先从getParameter中获取，其次getHeader
     * @param request
     * @return
     */
    public boolean interceptorTokenHeaderAndParam(HttpServletRequest request,HttpServletResponse response){
        String access_token=request.getParameter(Constants.CURRENT_ACCESS_TOKEN);
        if(access_token!=null){
            return isCurrentAccount(access_token);
        }else{
            access_token=request.getHeader(Constants.CURRENT_ACCESS_TOKEN);
            if(access_token!=null){
                return isCurrentAccount(access_token);
            }
        }
        return false;
    }

    /**
     * 获取当前认证账号并且存储于当前线程
     * @param access_token
     * @return
     */
    public boolean isCurrentAccount(String access_token){
        try {
            CurrentAccount currentAccount = webAuthenticationHandler.getCurrentAccount(access_token);
            if (currentAccount != null) {
                CurrentThreadLocal.set(currentAccount);
                return true;
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return false;
    }

    //afterCompletion是视图渲染完成之后才执行,同样需要preHandle返回true，
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
        //该方法通常用于清理资源等工作
    }

    /**
     * 将内容输出到浏览器
     */
    private final JSONObject message403=new JSONObject();
    private void writeContent403(HttpServletResponse response) {
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/plain;charset=UTF-8");
        response.setHeader("icop-content-type", "exception");
        response.setStatus(Constants.TOKEN_FAIL);
        PrintWriter writer = null;
        try {
            writer = response.getWriter();
        } catch (IOException e) {
            e.printStackTrace();
        }

        message403.put("code",Constants.TOKEN_FAIL);
        message403.put("message","无权访问接口，"+Constants.CURRENT_ACCESS_TOKEN+"凭据失效或者为空!");
        writer.print(message403.toString());
        writer.flush();
        writer.close();
    }

}